Imports System.ComponentModel
Imports WRDB.Project

Public Class clsGIS
    'Public Sub ShowGIS(ByVal _WRDBProject As clsProject, ByVal _TableName As String, ByVal _TempData As String, ByVal _Mode As frmGIS.enumMode, ByVal _WRDBRefreshStations As Boolean, ByVal _WRDBStationTypes As Generic.List(Of String))
    '    WRDBProject = _WRDBProject
    '    GISForm = Nothing
    '    GISForm = New frmGIS(WRDBProject, _Mode)
    '    ActiveTableName = _TableName
    '    TempData = _TempData
    '    WRDBRefreshStations = _WRDBRefreshStations
    '    WRDBStationTypes = _WRDBStationTypes
    '    With GISForm
    '        .Show()
    '    End With
    'End Sub
End Class

''' <summary>
''' Base class to store information for each layer in map
''' </summary>
''' <remarks>Note that all information is stored in the map layer object (not stored locally)</remarks>
Public MustInherit Class clsLayer
    Public LayerHandle As Integer
    Friend Map As AxMapWinGIS.AxMap

    Friend Sub New(ByVal GisMap As AxMapWinGIS.AxMap, ByVal Handle As Integer)
        Map = GisMap
        LayerHandle = Handle
        ShapeFileName = ShapeFile(Handle).Filename
    End Sub

    ''' <summary>
    ''' Convenience function to return shapefile object given layer handle
    ''' </summary>
    Friend Function ShapeFile(ByVal hdl As Integer) As MapWinGIS.Shapefile
        Return Map.get_GetObject(hdl)
    End Function

    ''' <summary>
    ''' Convenience function to return shapefile object for this layer
    ''' </summary>
    Friend Function ShapeFile() As MapWinGIS.Shapefile
        Return Map.get_GetObject(LayerHandle)
    End Function

    ''' <summary>
    ''' Shared function to create new map layer using specified shapefile
    ''' </summary>
    Friend Shared Function Add(ByVal Map As AxMapWinGIS.AxMap, ByVal FileName As String) As clsLayer
        Try
            With Map
                Dim sf As New MapWinGIS.Shapefile
                If sf.Open(FileName) Then
                    If String.IsNullOrEmpty(sf.Projection) Then

                        If WarningMsg("This shapefile ({0}) has no projection associated with it. Do you want to add it anyway?\n\n\t\b If you click 'OK', the current map projection will be used for this layer, which may cause objects to appear in the wrong location.\n\nWe recommend that you use a full-featured GIS program to assign or convert projections to all shapefiles you intend to view with WRDB.", IO.Path.GetFileName(FileName)) = DialogResult.Cancel Then Return Nothing

                    Else

                        'assign first projected shapefile as project projection
                        If (String.IsNullOrEmpty(ProjectProjection) Or .NumLayers = 0) And Not Map.IsSameProjection(sf.Projection, LatLongProjection) Then
                            ProjectProjection = sf.Projection
                        End If

                        'later ones must compare; if WRDB Stations layer already has been added, reproject it without comment
                        Dim IsStationsLayer As Boolean = IO.Path.GetFileNameWithoutExtension(FileName).Equals("WRDB Stations", StringComparison.OrdinalIgnoreCase)

                        If Not String.IsNullOrEmpty(ProjectProjection) AndAlso Not Map.IsSameProjection(sf.Projection, ProjectProjection) Then
                            If IsStationsLayer OrElse
                                WarningMsg("The shapefile is using a different projection than others in this map: {0}. Do you want to reproject it?\n\n" &
                                           "\t\b Click OK to create and load a new reprojected shape file with '-reproject' appended to the name.\n" &
                                           "\t\b Click Cancel to set this shapefile's projection the same as the map projection (which may cause shapes to appear incorrectly).", FileName.Replace("\", "/")) = DialogResult.OK Then
                                sf.Close()
                                If Not Reproject(Map, FileName, ProjectProjection, IsStationsLayer) Then Return Nothing
                                sf.Open(FileName)
                            Else
                                sf.Projection = ProjectProjection
                            End If
                        End If

                        'find existing WRDB Stations layer and make sure it uses this projection (will not apply if adding WRDB Stations at this time, because is not a layer yet)
                        For i As Integer = 0 To .NumLayers - 1
                            If String.Equals(.get_LayerName(.get_LayerHandle(i)), "WRDB Stations", StringComparison.OrdinalIgnoreCase) Then
                                Dim sf2 As MapWinGIS.Shapefile = .get_GetObject(.get_LayerHandle(i))
                                If Not Map.IsSameProjection(sf2.Projection, ProjectProjection) Then
                                    Dim fn As String = sf2.Filename
                                    sf2.Close()
                                    .RemoveLayer(.get_LayerHandle(i))
                                    If Reproject(Map, fn, ProjectProjection, True) Then
                                        Add(Map, fn)
                                    Else
                                        WarningMsg("Unable to reproject WRDB Stations shapefile to new projection.")
                                    End If
                                End If
                            End If
                        Next
                    End If

                    Dim lyr As clsLayer = Nothing
                    Dim LayerHandle As Integer = .AddLayer(sf, True)
                    Select Case sf.ShapefileType
                        Case MapWinGIS.ShpfileType.SHP_MULTIPATCH, MapWinGIS.ShpfileType.SHP_MULTIPOINT, MapWinGIS.ShpfileType.SHP_MULTIPOINTM, MapWinGIS.ShpfileType.SHP_MULTIPOINTZ, MapWinGIS.ShpfileType.SHP_POINT, MapWinGIS.ShpfileType.SHP_POINTM, MapWinGIS.ShpfileType.SHP_POINTZ
                            lyr = New clsLayerPoint(Map, LayerHandle)
                        Case MapWinGIS.ShpfileType.SHP_POLYGON, MapWinGIS.ShpfileType.SHP_POLYGONM, MapWinGIS.ShpfileType.SHP_POLYGONZ
                            lyr = New clsLayerPolygon(Map, LayerHandle)
                        Case MapWinGIS.ShpfileType.SHP_POLYLINE, MapWinGIS.ShpfileType.SHP_POLYLINEM, MapWinGIS.ShpfileType.SHP_POLYLINEZ
                            lyr = New clsLayerPolyline(Map, LayerHandle)
                    End Select
                    lyr.SetName(Strings.StrConv(IO.Path.GetFileNameWithoutExtension(FileName).Replace("-reproject", ""), VbStrConv.ProperCase))

                    'find max color used
                    Dim maxcolor As Integer = -1
                    For i As Integer = 0 To Map.NumLayers - 2
                        Dim hdl As Integer = Map.get_LayerHandle(i)
                        Dim clr As Color
                        If TypeOf Map.get_GetObject(hdl) Is MapWinGIS.Shapefile Then
                            Dim sf2 As MapWinGIS.Shapefile = Map.get_GetObject(hdl)
                            Select Case sf2.ShapefileType
                                Case MapWinGIS.ShpfileType.SHP_POINT
                                    clr = Map.get_ShapeLayerPointColor(hdl)
                                Case MapWinGIS.ShpfileType.SHP_POLYLINE
                                    clr = Map.get_ShapeLayerLineColor(hdl)
                                Case Else
                                    clr = Map.get_ShapeLayerFillColor(hdl)
                            End Select
                            For j As Integer = 0 To DefaultLayerColor.Length - 1
                                If DefaultLayerColor(j).ToArgb = clr.ToArgb Then
                                    maxcolor = Math.Max(maxcolor, j)
                                    Exit For
                                End If
                            Next
                        End If
                    Next
                    If TypeOf lyr Is clsLayerPoint Then
                        With CType(lyr, clsLayerPoint)
                            .PointColor = DefaultLayerColor(maxcolor + 1)
                            .PointSize = 10
                            .PointType = MapWinGIS.tkPointType.ptSquare
                        End With
                    ElseIf TypeOf lyr Is clsLayerPolygon Then
                        With CType(lyr, clsLayerPolygon)
                            .Filled = True
                            .FillColor = DefaultLayerColor(maxcolor + 1)
                            .LineColor = Color.Black
                            .FillStipple = MapWinGIS.tkFillStipple.fsNone
                        End With
                    Else
                        With CType(lyr, clsLayerPolyline)
                            .LineColor = DefaultLayerColor(maxcolor + 1)
                            .LineWidth = 1
                        End With
                    End If
                    Return lyr
                Else
                    WarningMsg("Unable to open shapefile: " & FileName)
                    Return Nothing
                End If
            End With
        Catch ex As Exception
            ErrorMsg(, ex)
            Return Nothing
        End Try
    End Function

    ''' <summary>
    ''' Create and return new layer object based on position in the layer list
    ''' </summary>
    Public Shared Function Reset(ByVal Map As AxMapWinGIS.AxMap, ByVal LayerPosition As Integer) As clsLayer
        Try
            Dim lyr As clsLayer = Nothing
            Dim LayerHandle As Integer = Map.get_LayerHandle(LayerPosition)
            Dim sf As MapWinGIS.Shapefile = Map.get_GetObject(LayerHandle)
            Select Case sf.ShapefileType
                Case MapWinGIS.ShpfileType.SHP_MULTIPATCH, MapWinGIS.ShpfileType.SHP_MULTIPOINT, MapWinGIS.ShpfileType.SHP_MULTIPOINTM, MapWinGIS.ShpfileType.SHP_MULTIPOINTZ, MapWinGIS.ShpfileType.SHP_POINT, MapWinGIS.ShpfileType.SHP_POINTM, MapWinGIS.ShpfileType.SHP_POINTZ
                    lyr = New clsLayerPoint(Map, LayerHandle)
                Case MapWinGIS.ShpfileType.SHP_POLYGON, MapWinGIS.ShpfileType.SHP_POLYGONM, MapWinGIS.ShpfileType.SHP_POLYGONZ
                    lyr = New clsLayerPolygon(Map, LayerHandle)
                Case MapWinGIS.ShpfileType.SHP_POLYLINE, MapWinGIS.ShpfileType.SHP_POLYLINEM, MapWinGIS.ShpfileType.SHP_POLYLINEZ
                    lyr = New clsLayerPolyline(Map, LayerHandle)
            End Select
            Return lyr
        Catch ex As Exception
            ErrorMsg(, ex)
            Return Nothing
        End Try
    End Function

    ''' <summary>
    ''' Create and return new layer object based on layer name
    ''' </summary>
    Public Shared Function Reset(ByVal Map As AxMapWinGIS.AxMap, ByVal LayerName As String) As clsLayer
        For i As Integer = 0 To Map.NumLayers - 1
            Dim LayerHandle As Integer = Map.get_LayerHandle(i)
            If Map.get_LayerName(LayerHandle).ToUpper = LayerName.ToUpper Then
                Return Reset(Map, i)
            End If
        Next
        Return Nothing
    End Function

    ''' <summary>
    ''' Helper routine to move current polygon layer below all non-polygon layers (so filled polygons don't obstruct)
    ''' </summary>
    Friend Sub MoveBelowPolylineLayers()
        Try
            If ShapeFile(LayerHandle).ShapefileType <> MapWinGIS.ShpfileType.SHP_POLYGON Then Exit Sub
            With Map
                For i As Integer = .get_LayerPosition(LayerHandle) - 1 To 0 Step -1
                    If ShapeFile(.get_LayerHandle(i)).ShapefileType <> MapWinGIS.ShpfileType.SHP_POLYGON Then
                        .MoveLayer(.get_LayerPosition(LayerHandle), i)
                    End If
                Next
            End With
        Catch ex As Exception
            ErrorMsg(, ex)
        End Try
    End Sub

    ''' <summary>
    ''' Move current layer down in list
    ''' </summary>
    Friend Sub MoveDown()
        With Map
            .MoveLayerDown(.get_LayerPosition(LayerHandle))
        End With
    End Sub

    ''' <summary>
    ''' Move current layer to top of list
    ''' </summary>
    Friend Sub MoveTop()
        With Map
            .MoveLayerTop(.get_LayerPosition(LayerHandle))
        End With
    End Sub

    ''' <summary>
    ''' Move current layer up in list
    ''' </summary>
    Friend Sub MoveUp()
        With Map
            .MoveLayerUp(.get_LayerPosition(LayerHandle))
        End With
    End Sub

    ''' <summary>
    ''' Remove current layer
    ''' </summary>
    Friend Sub Remove()
        With Map
            .RemoveLayer(LayerHandle)
        End With
    End Sub

    ''' <summary>
    ''' Control layer visibility
    ''' </summary>
    Friend Property Visible() As Boolean
        Get
            Return Map.get_LayerVisible(LayerHandle)
        End Get
        Set(ByVal value As Boolean)
            Map.set_LayerVisible(LayerHandle, value)
        End Set
    End Property

    ''' <summary>
    ''' Call this when you don't want to set Name property (which causes LoadLayers call) such as during loading
    ''' </summary>
    ''' <param name="Name">Layer name</param>
    Friend Sub SetName(ByVal Name As String)
        Map.set_LayerName(LayerHandle, Name)
    End Sub

    ''' <summary>
    ''' Load layer information from ini file
    ''' </summary>
    Friend Overridable Sub Load(ByVal IniFile As clsWRDBIniFile, ByVal LayerNum As Integer)
        With IniFile
            SetName(.GetKey("Layer_" & LayerNum, clsWRDBIniFile.enumKey.GISName, "Unknown"))
            Visible = .GetKey("Layer_" & LayerNum, clsWRDBIniFile.enumKey.GISVisible, "True")
        End With
    End Sub

    ''' <summary>
    ''' Save layer information to ini file
    ''' </summary>
    Friend Overridable Sub Save(ByVal IniFile As clsWRDBIniFile, ByVal LayerNum As Integer)
        With IniFile
            .SetKey("Layer_" & LayerNum, clsWRDBIniFile.enumKey.GISShapeFile, FileName)
            .SetKey("Layer_" & LayerNum, clsWRDBIniFile.enumKey.GISShapeFileRelative, GetRelativePath(IO.Path.GetDirectoryName(.FileName), FileName)) 'path relative to ini file
            .SetKey("Layer_" & LayerNum, clsWRDBIniFile.enumKey.GISName, Name)
            .SetKey("Layer_" & LayerNum, clsWRDBIniFile.enumKey.GISVisible, Visible.ToString)
        End With
    End Sub

#Region "Public properties for property grid"

    <DisplayName("(Name)"), Category("(General)"), Description("Layer name.")> _
    Public Property Name() As String
        Get
            Return Map.get_LayerName(LayerHandle)
        End Get
        Set(ByVal value As String)
            Map.set_LayerName(LayerHandle, value)
            If GISForm IsNot Nothing Then GISForm.RefreshLayerList()
        End Set
    End Property

    <DisplayName("File Name"), Category("(General)"), Description("Shape file name."), [ReadOnly](True)> _
    Public ReadOnly Property FileName() As String
        Get
            Dim sf As MapWinGIS.Shapefile = Map.get_GetObject(LayerHandle)
            If sf Is Nothing Then Return "" Else Return sf.Filename
        End Get
    End Property

    'note: to avoid having to save layer structure elsewhere, use LayerKey placeholder to save data file and field names

    <DisplayName("File Name"), Category("Data File Mapping"), Description("Data file name."), [ReadOnly](True)> _
    Public Property DataFile() As String
        Get
            Dim Tag() As String = Map.get_LayerKey(LayerHandle).Split(";")
            If Tag.Length >= 1 AndAlso Not String.IsNullOrEmpty(Tag(0)) Then
                Return Tag(0)
            Else
                Return "Not used"
            End If
        End Get
        Set(ByVal value As String)
            Dim Tag() As String = Map.get_LayerKey(LayerHandle).Split(";")
            If Tag.Length >= 2 Then
                Map.set_LayerKey(LayerHandle, value & ";" & Tag(1))
            Else
                Map.set_LayerKey(LayerHandle, value & ";")
            End If
        End Set
    End Property

    <DisplayName("Field Name"), Category("Data File Mapping"), Description("Data file name."), [ReadOnly](True)> _
    Public Property DataField() As String
        Get
            Dim Tag() As String = Map.get_LayerKey(LayerHandle).Split(";")
            If Tag.Length >= 2 AndAlso Not String.IsNullOrEmpty(Tag(1)) Then
                Return Tag(1)
            Else
                Return "Not used"
            End If
        End Get
        Set(ByVal value As String)
            Dim Tag() As String = Map.get_LayerKey(LayerHandle).Split(";")
            If Tag.Length >= 1 Then
                Map.set_LayerKey(LayerHandle, Tag(0) & ";" & value)
            Else
                Map.set_LayerKey(LayerHandle, ";" & value)
            End If
        End Set
    End Property

#End Region

End Class




Public Class clsLayerPoint : Inherits clsLayer
    Friend Sub New(ByVal GisMap As AxMapWinGIS.AxMap, ByVal Handle As Integer)
        MyBase.New(GisMap, Handle)
    End Sub

    Friend Overrides Sub Load(ByVal IniFile As clsWRDBIniFile, ByVal LayerNum As Integer)
        MyBase.Load(IniFile, LayerNum)
        With IniFile
            PointColor = Drawing.Color.FromName(.GetKey("Layer_" & LayerNum, clsWRDBIniFile.enumKey.GISPointColor, "Unknown"))
            PointSize = .GetKey("Layer_" & LayerNum, clsWRDBIniFile.enumKey.GISPointSize, "10")
            PointType = [Enum].Parse(GetType(MapWinGIS.tkPointType), .GetKey("Layer_" & LayerNum, clsWRDBIniFile.enumKey.GISPointType, MapWinGIS.tkPointType.ptSquare.ToString))
        End With
    End Sub

    Friend Overrides Sub Save(ByVal IniFile As clsWRDBIniFile, ByVal LayerNum As Integer)
        MyBase.Save(IniFile, LayerNum)
        With IniFile
            .SetKey("Layer_" & LayerNum, clsWRDBIniFile.enumKey.GISPointColor, PointColor.Name)
            .SetKey("Layer_" & LayerNum, clsWRDBIniFile.enumKey.GISPointSize, PointSize.ToString)
            .SetKey("Layer_" & LayerNum, clsWRDBIniFile.enumKey.GISPointType, PointType.ToString)
        End With
    End Sub

    <DisplayName("Color"), Category("Point Settings"), Description("Point color.")> _
    Public Property PointColor() As Drawing.Color
        Get
            Return Map.get_ShapeLayerPointColor(LayerHandle)
        End Get
        Set(ByVal value As Drawing.Color)
            Map.set_ShapeLayerPointColor(LayerHandle, MapColor(value))
        End Set
    End Property

    <DisplayName("Size"), Category("Point Settings"), Description("Point size.")> _
    Public Property PointSize() As Single
        Get
            Return Map.get_ShapeLayerPointSize(LayerHandle)
        End Get
        Set(ByVal value As Single)
            Map.set_ShapeLayerPointSize(LayerHandle, value)
        End Set
    End Property

    <DisplayName("Type"), Category("Point Settings"), Description("Point type.")> _
    Public Property PointType() As MapWinGIS.tkPointType
        Get
            Return Map.get_ShapeLayerPointType(LayerHandle)
        End Get
        Set(ByVal value As MapWinGIS.tkPointType)
            Map.set_ShapeLayerPointType(LayerHandle, value)
        End Set
    End Property

End Class




Public Class clsLayerPolyline : Inherits clsLayer
    Friend Sub New(ByVal GisMap As AxMapWinGIS.AxMap, ByVal Handle As Integer)
        MyBase.New(GisMap, Handle)
    End Sub

    Friend Overrides Sub Load(ByVal IniFile As clsWRDBIniFile, ByVal LayerNum As Integer)
        MyBase.Load(IniFile, LayerNum)
        With IniFile
            LineColor = Drawing.Color.FromName(.GetKey("Layer_" & LayerNum, clsWRDBIniFile.enumKey.GISLineColor, "Black"))
            LineWidth = .GetKey("Layer_" & LayerNum, clsWRDBIniFile.enumKey.GISLineWidth, "0")
            LineStipple = [Enum].Parse(GetType(MapWinGIS.tkLineStipple), .GetKey("Layer_" & LayerNum, clsWRDBIniFile.enumKey.GISLineStipple, MapWinGIS.tkLineStipple.lsNone.ToString))
        End With
    End Sub

    Friend Overrides Sub Save(ByVal IniFile As clsWRDBIniFile, ByVal LayerNum As Integer)
        MyBase.Save(IniFile, LayerNum)
        With IniFile
            .SetKey("Layer_" & LayerNum, clsWRDBIniFile.enumKey.GISLineColor, LineColor.Name)
            .SetKey("Layer_" & LayerNum, clsWRDBIniFile.enumKey.GISLineWidth, LineWidth.ToString)
            .SetKey("Layer_" & LayerNum, clsWRDBIniFile.enumKey.GISLineStipple, LineStipple.ToString)
        End With
    End Sub

    <DisplayName("Color"), Category("Polyline Settings"), Description("Line color.")> _
    Public Property LineColor() As Drawing.Color
        Get
            Return Map.get_ShapeLayerLineColor(LayerHandle)
        End Get
        Set(ByVal value As Drawing.Color)
            Map.set_ShapeLayerLineColor(LayerHandle, MapColor(value))
        End Set
    End Property

    <DisplayName("Width"), Category("Polyline Settings"), Description("Line width.")> _
    Public Property LineWidth() As Single
        Get
            Return Map.get_ShapeLayerLineWidth(LayerHandle)
        End Get
        Set(ByVal value As Single)
            Map.set_ShapeLayerLineWidth(LayerHandle, value)
        End Set
    End Property

    <DisplayName("Pattern"), Category("Polyline Settings"), Description("Pattern used for border")> _
    Public Property LineStipple() As MapWinGIS.tkLineStipple
        Get
            Return Map.get_ShapeLayerLineStipple(LayerHandle)
        End Get
        Set(ByVal value As MapWinGIS.tkLineStipple)
            Map.set_ShapeLayerLineStipple(LayerHandle, value)
        End Set
    End Property

End Class



Public Class clsLayerPolygon : Inherits clsLayerPolyline
    Friend Sub New(ByVal GisMap As AxMapWinGIS.AxMap, ByVal Handle As Integer)
        MyBase.New(GisMap, Handle)
    End Sub

    Friend Overrides Sub Load(ByVal IniFile As clsWRDBIniFile, ByVal LayerNum As Integer)
        MyBase.Load(IniFile, LayerNum)
        With IniFile
            Filled = .GetKey("Layer_" & LayerNum, clsWRDBIniFile.enumKey.GISFilled, "True")
            FillColor = Drawing.Color.FromName(.GetKey("Layer_" & LayerNum, clsWRDBIniFile.enumKey.GISFillColor, "White"))
            FillStipple = [Enum].Parse(GetType(MapWinGIS.tkFillStipple), .GetKey("Layer_" & LayerNum, clsWRDBIniFile.enumKey.GISFillStipple, MapWinGIS.tkFillStipple.fsNone.ToString))
            FillTransparency = .GetKey("Layer_" & LayerNum, clsWRDBIniFile.enumKey.GISFillTransparency, "1")
        End With
    End Sub

    Friend Overrides Sub Save(ByVal IniFile As clsWRDBIniFile, ByVal LayerNum As Integer)
        MyBase.Save(IniFile, LayerNum)
        With IniFile
            .SetKey("Layer_" & LayerNum, clsWRDBIniFile.enumKey.GISFilled, Filled.ToString)
            .SetKey("Layer_" & LayerNum, clsWRDBIniFile.enumKey.GISFillColor, FillColor.Name)
            .SetKey("Layer_" & LayerNum, clsWRDBIniFile.enumKey.GISFillStipple, FillStipple.ToString)
            .SetKey("Layer_" & LayerNum, clsWRDBIniFile.enumKey.GISFillTransparency, FillTransparency.ToString)
        End With
    End Sub

    <DisplayName("Filled?"), Category("Polygon Fill Settings"), Description("Shapes are filled?")> _
    Public Property Filled() As Boolean
        Get
            Return Map.get_ShapeLayerDrawFill(LayerHandle)
        End Get
        Set(ByVal value As Boolean)
            Map.set_ShapeLayerDrawFill(LayerHandle, value)
        End Set
    End Property

    <DisplayName("Color"), Category("Polygon Fill Settings"), Description("Fill color.")> _
    Public Property FillColor() As Drawing.Color
        Get
            Return Map.get_ShapeLayerFillColor(LayerHandle)
        End Get
        Set(ByVal value As Drawing.Color)
            Map.set_ShapeLayerFillColor(LayerHandle, MapColor(value))
        End Set
    End Property

    <DisplayName("Pattern"), Category("Polygon Fill Settings"), Description("Pattern used to fill shapes")> _
    Public Property FillStipple() As MapWinGIS.tkFillStipple
        Get
            Return Map.get_ShapeLayerFillStipple(LayerHandle)
        End Get
        Set(ByVal value As MapWinGIS.tkFillStipple)
            Map.set_ShapeLayerFillStipple(LayerHandle, value)
        End Set
    End Property

    <DisplayName("Transparency"), Category("Polygon Fill Settings"), Description("Transparency used to fill shapes")> _
    Public Property FillTransparency() As Single
        Get
            Return Map.get_ShapeLayerFillTransparency(LayerHandle)
        End Get
        Set(ByVal value As Single)
            Map.set_ShapeLayerFillTransparency(LayerHandle, value)
        End Set
    End Property

End Class

'Public Class ImageConverter
'    Inherits System.Windows.Forms.AxHost
'    Public Sub New()
'        MyBase.New("00000000-9999-0000-9999-000000000001")
'    End Sub
'    Public Function ImageToPicture(ByRef Data As Image) As Object
'        Return AxHost.GetIPictureDispFromPicture(Data)
'    End Function
'End Class

Public Module modGIS
    <System.Runtime.InteropServices.DllImportAttribute("gdi32.dll")> _
    Friend Function BitBlt(ByVal hdcDest As IntPtr, ByVal nXDest As Integer, ByVal nYDest As Integer, ByVal nWidth As Integer, ByVal nHeight As Integer, ByVal hdcSrc As IntPtr, ByVal nXSrc As Integer, ByVal nYSrc As Integer, ByVal dwRop As System.Int32) As Boolean
    End Function
    Public DefaultLayerColor(1399) As Drawing.Color
    Friend GISForm As frmGIS
    Public ProjectProjection As String
    Public Const LatLongProjection As String = "+proj=latlong +ellps=WGS84 +datum=WGS84" '"+proj=longlat +ellps=WGS84 +datum=WGS84 +no_defs"
    Friend ShapeFileName As String 'shared so typeconverter can display list of fields
    Friend WRDBProject As WRDB.Project.clsProject
    Friend ActiveTableName As String
    Friend TempData As String
    Friend WRDBStationTypes As New Generic.List(Of String) 'prior list of station types (so won't have to requery data maybe)

    ''' <summary>List of stations to display (Stations mode only); string must be tab separated and contain StationID, Name, Type, Lat, Long</summary>
    Friend StationList As New Generic.List(Of String)

    ''' <summary>
    ''' Name of directory for temporary files (does NOT end with backslash)
    ''' </summary>
    Friend TempPath As String = String.Format("{0}\WRDB", My.Computer.FileSystem.SpecialDirectories.Temp)

    Public Function MapColor(ByVal SystemColor As Color) As UInt32
        Return System.Convert.ToUInt32(RGB(SystemColor.R, SystemColor.G, SystemColor.B))
    End Function

    ''' <summary>
    ''' Reproject a shapefile to a new projection
    ''' </summary>
    ''' <param name="Map">Map object</param>
    ''' <param name="ShapeFileName">Old shapefile name; if ReplaceOrig is false, this returns the newly reprojected shape file name</param>
    ''' <param name="NewProj">New projection string</param>
    ''' <param name="ReplaceOrig">If true, will replace the original shape file with the new one</param>
    Public Function Reproject(ByVal Map As AxMapWinGIS.AxMap, ByRef ShapeFileName As String, ByVal NewProj As String, ByVal ReplaceOrig As Boolean) As Boolean
        Dim sf As New MapWinGIS.Shapefile
        sf.Open(ShapeFileName)
        With sf
            If .NumShapes > 0 And Not Map.IsSameProjection(.Projection, NewProj) Then
                MapWinGeoProc.Error.ClearErrorLog()
                Dim NewFilename As String = .Filename.Replace(".shp", "-reproject.shp")
                If My.Computer.FileSystem.FileExists(NewFilename) Then MapWinGeoProc.DataManagement.DeleteShapefile(NewFilename)
                Dim OldProj As String = .Projection
                .Close()
                If MapWinGeoProc.SpatialReference.ProjectShapefile(OldProj, NewProj, ShapeFileName, NewFilename) Then
                    If ReplaceOrig Then
                        If Not MapWinGeoProc.DataManagement.DeleteShapefile(ShapeFileName) Then Return False
                        If Not MapWinGeoProc.DataManagement.RenameShapefile(NewFilename, ShapeFileName) Then Return False
                    Else
                        ShapeFileName = NewFilename
                    End If
                Else
                    WarningMsg("Unable to reproject the shape file: \n\n{0}\n\nError message was:\n\n{1}", ShapeFileName.Replace("\", "/"), MapWinGeoProc.Error.GetLastErrorMsg)
                    Return False
                End If
            End If
        End With
        Return True
    End Function

#Region "Map Functions..."

    Friend Function GetShapeFile(ByVal GISMap As AxMapWinGIS.AxMap, ByVal LayerName As String) As MapWinGIS.Shapefile
        Dim hdl As Integer = GetLayerHandle(GISMap, LayerName)
        If TypeOf (GISMap.get_GetObject(hdl)) Is MapWinGIS.Shapefile AndAlso hdl <> -1 Then Return GISMap.get_GetObject(hdl) Else Return Nothing
    End Function

    Friend Function GetShapeFile(ByVal GISMap As AxMapWinGIS.AxMap, ByVal LayerPosition As Integer) As MapWinGIS.Shapefile
        Dim hdl As Integer = GISMap.get_LayerHandle(LayerPosition)
        If TypeOf (GISMap.get_GetObject(hdl)) Is MapWinGIS.Shapefile AndAlso hdl <> -1 Then Return GISMap.get_GetObject(hdl) Else Return Nothing
    End Function

    Friend Function GetLayerHandle(ByVal GISMap As AxMapWinGIS.AxMap, ByVal LayerName As String) As Integer
        For i As Integer = GISMap.NumLayers - 1 To 0 Step -1
            Dim hdl As Integer = GISMap.get_LayerHandle(i)
            If GISMap.get_LayerName(hdl).Equals(LayerName, StringComparison.OrdinalIgnoreCase) Then Return hdl
        Next
        Return -1
    End Function

    Friend Function GetFieldIndex(ByVal sf As MapWinGIS.Shapefile, ByVal FieldName As String)
        For i As Integer = 0 To sf.NumFields - 1
            If sf.Field(i).Name.Equals(FieldName, StringComparison.OrdinalIgnoreCase) Then Return i
        Next
        Return -1
    End Function

#End Region


End Module


''' <summary>
''' This was tested for display of available field names in selected layer, but decided to go another direction
''' </summary>
''' <remarks></remarks>
Public Class FieldListConverter
    Inherits TypeConverter

    Public Overrides Function GetStandardValuesSupported(ByVal context As System.ComponentModel.ITypeDescriptorContext) As Boolean
        Return True
    End Function

    Public Overrides Function GetStandardValuesExclusive(ByVal context As System.ComponentModel.ITypeDescriptorContext) As Boolean
        Return True
    End Function

    Public Overrides Function GetStandardValues(ByVal context As System.ComponentModel.ITypeDescriptorContext) As System.ComponentModel.TypeConverter.StandardValuesCollection
        Dim sf As New MapWinGIS.Shapefile
        sf.Open(ShapeFileName)

        Dim lstFields As New Generic.List(Of String)

        lstFields.Add("(None)")
        For i As Integer = 0 To sf.NumFields - 1
            lstFields.Add(sf.Field(i).Name)
        Next
        lstFields.Sort()
        Return New StandardValuesCollection(lstFields)
    End Function
End Class
